﻿// Inner Fire 游戏引擎库
// Lua绑定适配项目
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层(4)
// 用于Object的Lua绑定适配。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-30

#include "game/animation/animator.h"
#include "game/object/camera_object.h"
#include "lua_manager.h"
#include <game/component/attacher.h>
#include <game/object/instanced_sprite_object.h>
#include <game/object/map_object.h>
#include <game/physics/collider.h>

namespace ifire::game {

static int Transform_SetPosition(lua_State* L) {
  auto ptr = L_THIS(Transform);
  ptr->SetPosition(L_VEC3(2));
  return 0;
}

static int Transform_SetRotation(lua_State* L) {
  auto ptr = L_THIS(Transform);
  ptr->SetRotationEular(L_VEC3(2));
  return 0;
}

static int Transform_SetScale(lua_State* L) {
  auto ptr = L_THIS(Transform);
  ptr->SetScale(L_VEC3(2));
  return 0;
}

static int Transform_SetSpring(lua_State* L) {
  auto ptr = L_THIS(Transform);
  ptr->SetSpring(L_VEC3(2), L_VEC3(5), L_FLOAT(8));
  return 0;
}

static int Transform_GetPosition(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->GetPosition());
}
static int Transform_GetRotation(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->GetRotationEular());
}

static int Transform_GetForward(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->GetForward());
}

static int Transform_GetScale(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->GetScale());
}

static int Transform_TransformDirection(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->TransformDirection(L_VEC3(2)));
}

static int Transform_TransformForward(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->TransformForward(L_VEC3(2)));
}

static int Transform_LookTowardLerp(lua_State* L) {
  auto ptr = L_THIS(Transform);
  return ikit::lua_return_float3(L, ptr->LookTowardLerp(L_VEC3(2), L_FLOAT(5)));
}

static int Attacher_AttachTo(lua_State* L) {
  auto ptr = L_THIS(Attacher);
  auto obj = ikit::lua_get_no_check<GameObject>(L, 2);
  ikit::sstr slot(L_STR(3));
  ptr->AttachTo(obj, slot);
  return 0;
}

static int Attacher_SetModify(lua_State* L) {
  auto ptr = L_THIS(Attacher);
  ptr->SetModify(L_VEC3(2), L_VEC3(5), L_VEC3(8));
  return 0;
}

static int Attacher_UseModify(lua_State* L) {
  auto ptr = L_THIS(Attacher);
  ptr->UseModify(L_BOOL(2));
  return 0;
}

static int Attacher_GetAdjust(lua_State* L) {
  auto ptr = L_THIS(Attacher);
  IVec3 pos, rot, scl;
  ptr->GetAdjust(pos, rot, scl);
  lua_pushnumber(L, pos.x);
  lua_pushnumber(L, pos.y);
  lua_pushnumber(L, pos.z);
  lua_pushnumber(L, rot.x);
  lua_pushnumber(L, rot.y);
  lua_pushnumber(L, rot.z);
  lua_pushnumber(L, scl.x);
  lua_pushnumber(L, scl.y);
  lua_pushnumber(L, scl.z);
  return 9;
}

static int GameObject_SetPosition(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ptr->GetTransform().SetPosition(L_VEC3(2));
  return 0;
}

static int GameObject_SetRotation(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ptr->GetTransform().SetRotationEular(L_VEC3(2));
  return 0;
}

static int GameObject_SetScale(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ptr->GetTransform().SetScale(L_VEC3(2));
  return 0;
}

static int GameObject_AttachObject(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ikit::sstr name = L_STR(2);
  // 将Lua对象存入Registry并获取引用ID
  lua_pushvalue(L, 3);                              // 复制要存储的对象到栈顶
  int register_id = luaL_ref(L, LUA_REGISTRYINDEX); // 返回的refKey需要被管理
  // 加入到GameObject中
  ptr->AttachLuaObject(name, register_id);
  return 0;
}

static int GameObject_GetObject(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  auto obj_id = ptr->GetLuaObject(L_STR(2));
  lua_rawgeti(L, LUA_REGISTRYINDEX, obj_id); // 从Registry取回
  return 1;
}

static int GameObject_GetName(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  lua_pushstring(L, ptr->GetName().c_str());
  return 1;
}

static int GameObject_GetUID(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  lua_pushinteger(L, ptr->GetUID());
  return 1;
}

static int GameObject_PrintInfo(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ikit::sstr type_name(L_STR(2));
  ptr->PrintInfo(type_name);
  return 0;
}

static int GameObject_GetTransform(lua_State* L) {
  // 注意这里，这个no_check不再检查元表。所以能够使用继承。
  auto ptr = ikit::lua_get_no_check<GameObject>(L, 1);
  return ikit::lua_return_object(L, &ptr->GetTransform(), "TransformMeta");
}

static int GameObject_AddComponent(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  ikit::sstr component_name(L_STR(2));
  auto component = ptr->AddComponent(component_name);
  return ikit::lua_return_object(L, component, component->GetMetaName());
}

static int GameObject_AddRigidBody(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  auto component = ptr->AddRigidBody();
  return ikit::lua_return_object(L, component, "RigidBodyMeta");
}

static int GameObject_AddCollider(lua_State* L) {
  auto ptr = L_THIS(GameObject);
  auto component = ptr->AddCollider();
  return ikit::lua_return_object(L, component, "ColliderMeta");
}

static int Camera_SetCameraParam(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  float fov = L_FLOAT(2);
  float near_z = L_FLOAT(3);
  float far_z = L_FLOAT(4);
  ptr->SetCameraParam((float)fov, (float)near_z, (float)far_z);
  return 0;
}

static int Camera_SetCameraRotation(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  float pitch = L_FLOAT(2);
  float yaw = L_FLOAT(3);
  float roll = L_FLOAT(4);
  ptr->SetCameraRotation((float)pitch, (float)yaw, (float)roll);
  return 0;
}

static int Camera_SetFollow(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  auto transform = L_OBJ(2, Transform);
  ptr->SetFollow(transform);
  return 0;
}

static int Camera_SetOffset(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  ptr->SetOffset(L_VEC3(2));
  return 0;
}

static int Camera_UpdateFollow(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  ptr->UpdateFollow();
  return 0;
}

static int Camera_TransformAxis(lua_State* L) {
  auto ptr = L_THIS(CameraObject);
  return lua_return_float3(L, ptr->TransformAxis(L_VEC2(2)));
}

static int InstancedSprite_SetPosition(lua_State* L) {
  auto ptr = L_THIS(InstancedSpriteObject);
  auto index = L_INT(2);
  ptr->SetPosition(L_INT(2), L_VEC3(3));
  return 0;
}

static int InstancedSprite_SetAllScale(lua_State* L) {
  auto ptr = L_THIS(InstancedSpriteObject);
  ptr->SetAllScale(L_VEC3(2));
  return 0;
}

static int InstancedSprite_SetAllColor(lua_State* L) {
  auto ptr = L_THIS(InstancedSpriteObject);
  float r = L_FLOAT(2);
  float g = L_FLOAT(3);
  float b = L_FLOAT(4);
  float a = L_FLOAT(5);
  ptr->SetAllColor(IVec4(r, g, b, a));
  return 0;
}

static int MapObject_SetPosition(lua_State* L) {
  auto ptr = L_THIS(MapObject);
  ptr->SetPosition(L_VEC3(2));
  return 0;
}

void register_lua_objects(lua_State* L, LuaManager* lua_manager) {

  // 注册Transform的元表
  luaL_Reg transform_methods[] = {                          //
      {"SetPosition", Transform_SetPosition},               //
      {"SetRotation", Transform_SetRotation},               //
      {"SetScale", Transform_SetScale},                     //
      {"GetPosition", Transform_GetPosition},               //
      {"GetRotation", Transform_GetRotation},               //
      {"GetScale", Transform_GetScale},                     //
      {"SetSpring", Transform_SetSpring},                   //
      {"GetForward", Transform_GetForward},                 //
      {"TransformDirection", Transform_TransformDirection}, //
      {"TransformForward", Transform_TransformForward},     //
      {"LookTowardLerp", Transform_LookTowardLerp},         //
      {NULL, NULL}};
  lua_register_metatable(L, "TransformMeta", transform_methods);

  // 注册Attach组件
  luaL_Reg attacher_methods[] = {        //
      {"AttachTo", Attacher_AttachTo},   //
      {"SetModify", Attacher_SetModify}, //
      {"UseModify", Attacher_UseModify}, //
      {"GetAdjust", Attacher_GetAdjust}, //
      {NULL, NULL}};
  lua_register_metatable(L, "AttacherMeta", attacher_methods);

  // 注册GameObject的元表
  luaL_Reg game_object_methods[] = {             //
      {"GetName", GameObject_GetName},           //
      {"GetUID", GameObject_GetUID},             //
      {"PrintInfo", GameObject_PrintInfo},       //
      {"AddComponent", GameObject_AddComponent}, //
      {"AddRigidBody", GameObject_AddRigidBody}, //
      {"AddCollider", GameObject_AddCollider},   //
      {"GetTransform", GameObject_GetTransform}, //
      {"SetPosition", GameObject_SetPosition},   //
      {"SetRotation", GameObject_SetRotation},   //
      {"SetScale", GameObject_SetScale},         //
      {"AttachObject", GameObject_AttachObject}, //
      {"GetObject", GameObject_GetObject},       //

      {NULL, NULL}};
  lua_register_metatable(L, "GameObjectMeta", game_object_methods);

  // 注册CameraObject的元表（继承自Object）
  luaL_Reg camera_methods[] = {                        //
      {"SetCameraParam", Camera_SetCameraParam},       //
      {"SetCameraRotation", Camera_SetCameraRotation}, //
      {"SetFollow", Camera_SetFollow},                 //
      {"SetOffset", Camera_SetOffset},                 //
      {"UpdateFollow", Camera_UpdateFollow},           //
      {"TransformAxis", Camera_TransformAxis},         //
      {NULL, NULL}};
  lua_register_metatable_inheritance(
      L, "CameraObjectMeta", "GameObjectMeta", camera_methods);

  // 注册InstancedSprite的元表（继承自Object）
  luaL_Reg instanced_sprite_methods[] = {           //
      {"SetPosition", InstancedSprite_SetPosition}, //
      {"SetAllScale", InstancedSprite_SetAllScale}, //
      {"SetAllColor", InstancedSprite_SetAllColor}, //
      {NULL, NULL}};
  lua_register_metatable_inheritance(L, "InstancedSpriteObjectMeta",
      "GameObjectMeta", instanced_sprite_methods);

  // 注册MapObject的元表（继承自Object）
  luaL_Reg map_object_methods[] = {           //
      {"SetPosition", MapObject_SetPosition}, //
      {NULL, NULL}};
  lua_register_metatable_inheritance(
      L, "MapObjectMeta", "GameObjectMeta", map_object_methods);
}
} // namespace ifire::game